package org.xhy.sniffer;

import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.utility.JavaModule;
import org.xhy.sniffer.boot.ServiceManager;
import org.xhy.sniffer.config.Config;
import org.xhy.sniffer.plugin.AbstractClassEnhancePluginDefine;
import org.xhy.sniffer.plugin.PluginBootstrap;
import org.xhy.sniffer.plugin.PluginFinder;

import java.lang.instrument.Instrumentation;
import java.util.List;
import java.util.Properties;

/**
 * -javaagent:/Users/xhy/IdeaProjects/xhy-skywalking/dist/agent-1.0-SNAPSHOT-jar-with-dependencies.jar
 * @description:
 * @gitee: https://gitee.com/XhyQAQ
 * @copyright: B站: https://space.bilibili.com/152686439
 * @Author: Xhy
 * @CreateTime: 2024-07-11 19:11
 */
@Slf4j
public class Agent {
    /**
     * 主入口
     * @param args
     * @param instrumentation
     */
    public static void premain(String args, Instrumentation instrumentation) {

        log.info("进入到 premain,args:{}",args);
        PluginFinder pluginFinder;
        try {
            // 加载插件
            pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
        }catch (Exception e) {
            log.error("初始化失败",e);
            return;
        }
        ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(true));
        AgentBuilder builder = new AgentBuilder.Default(byteBuddy);

        // 构建匹配规则
        builder.type(pluginFinder.buildMatch())
                // 转换
                .transform(new Transformer(pluginFinder))
                .installOn(instrumentation);
        Properties properties = Config.getInstance().getProperties();
        ServiceManager.INSTANCE.loadAllServices(properties);
    }

    private static class Transformer implements AgentBuilder.Transformer{

        private PluginFinder pluginFinder;

        public Transformer(PluginFinder pluginFinder) {
            this.pluginFinder = pluginFinder;
        }

        /**
         *
         * @param builder 原对象
         * @param typeDescription 类描述
         * @param classLoader 加载器
         * @param module
         * @return
         */
        @Override
        public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                                TypeDescription typeDescription,
                                                // 加载 typeDescription这个类的类加载器
                                                ClassLoader classLoader,
                                                JavaModule module) {
            log.info("actualName to transform:{}", typeDescription.getActualName());
            // 找到当前类对应的插件
            List<AbstractClassEnhancePluginDefine> pluginDefines = pluginFinder.find(typeDescription);
            if (pluginDefines.size() > 0) {
                DynamicType.Builder<?> newBuilder = builder;
                // 插桩
                for (AbstractClassEnhancePluginDefine pluginDefine : pluginDefines) {
                    DynamicType.Builder<?> possibleNewBuilder = pluginDefine.define(typeDescription,newBuilder,classLoader);
                    if (possibleNewBuilder != null) {
                        newBuilder = possibleNewBuilder;
                    }
                }

                return newBuilder;
            }
            log.debug("匹配到了类:{},但是未find到插件集合",typeDescription.getActualName());
            return builder;

        }
    }
}
